// 技能CD技能
// TODO 如果后期卡的话，可以改异步帧刷新调用技能施法的时候发同步信息
// @author:wangff8@qq.com  @date:2024-11-10
library SkillButtonVo initializer init requires SkillButtonUI, AttackSys

    globals
        // 技能按钮数据
        // 父key StringHash("技能数量")，子key uid 分别表示每个玩家的添加技能的数量
        // 父key 按钮id 1 - 10
        // 子key [uid * 100 + id]
        // id = 1 表示按钮是否启动   id = 2 当前按钮绑定的技能id  id = 3 当前按钮的进行CD的计时  id = 4 当前按钮的进行CD时间
        // id = 5 当前按钮的结束CD计时 id = 6 当前按钮的结束CD时间
        // id = 7 当前按钮的显示图标
        // id = 8 进行是CD显示进度
        // id = 9 结束CD显示进度
        hashtable skillBtnHash = InitHashtable()
    endglobals

    // 设置技能按钮数量
    function setSkillButtonNum takes integer uid, integer num returns nothing
        call SaveInteger(skillBtnHash, StringHash("技能数量"), uid, num)
    endfunction
    // 获取技能按钮数量
    function getSkillButtonNum takes integer uid returns integer
        return LoadInteger(skillBtnHash, StringHash("技能数量"), uid)
    endfunction

    // 启动技能按钮
    function startSkillButton takes integer uid, integer btnId returns nothing
        call SaveBoolean(skillBtnHash, btnId, uid * 100 + 1, true)
    endfunction
    // 判断按钮是否启动
    function isSkillButtonStart takes integer uid, integer btnId returns boolean
        return LoadBoolean(skillBtnHash, btnId, uid * 100 + 1)
    endfunction

    // 设置按钮绑定的技能id
    function setSkillButtonSkillId takes integer uid, integer btnId, integer skillId returns nothing
        call SaveInteger(skillBtnHash, btnId, uid * 100 + 2, skillId)
    endfunction
    // 获取按钮绑定的技能id
    function getSkillButtonSkillId takes integer uid, integer btnId returns integer
        return LoadInteger(skillBtnHash, btnId, uid * 100 + 2)
    endfunction

    // 设置按钮的进行时CD
    function setSkillButtonStartingCD takes integer uid, integer btnId, real cd returns nothing
        call SaveReal(skillBtnHash, btnId, uid * 100 + 4, cd)
    endfunction
    // 获取按钮的进行时CD
    function getSkillButtonStartingCD takes integer uid, integer btnId returns real
        return LoadReal(skillBtnHash, btnId, uid * 100 + 4)
    endfunction
    // 设置CD进行时按钮模型显示进度，1为显示全
    function setSkillButtonStartingCDProgress takes integer uid, integer btnId, real progress returns nothing
        call SaveReal(skillBtnHash, btnId, uid * 100 + 8, progress)
    endfunction
    // 获取CD进行时按钮模型显示进度
    function getSkillButtonStartingCDProgress takes integer uid, integer btnId returns real
        return LoadReal(skillBtnHash, btnId, uid * 100 + 8)
    endfunction
    // 设置按钮的进行时CD的计时
    function setSkillButtonStartingCDTime takes integer uid, integer btnId, real time returns nothing
        call SaveReal(skillBtnHash, btnId, uid * 100 + 3, time)
    endfunction
    // 获取按钮的进行时CD的计时
    function getSkillButtonStartingCDTime takes integer uid, integer btnId returns real
        return LoadReal(skillBtnHash, btnId, uid * 100 + 3)
    endfunction
    // 设置按钮的施法结束CD
    function setSkillButtonEndingCD takes integer uid, integer btnId, real cd returns nothing
        call SaveReal(skillBtnHash, btnId, uid * 100 + 6, cd)
    endfunction
    // 获取按钮的施法结束CD
    function getSkillButtonEndingCD takes integer uid, integer btnId returns real
        return LoadReal(skillBtnHash, btnId, uid * 100 + 6)
    endfunction
    // 设置CD结束时按钮模型显示进度
    function setSkillButtonEndingCDProgress takes integer uid, integer btnId, real progress returns nothing
        call SaveReal(skillBtnHash, btnId, uid * 100 + 9, progress)
    endfunction
    // 获取CD结束时按钮模型显示进度
    function getSkillButtonEndingCDProgress takes integer uid, integer btnId returns real
        return LoadReal(skillBtnHash, btnId, uid * 100 + 9)
    endfunction
    // 设置按钮的施法结束CD计时
    function setSkillButtonEndingCDTime takes integer uid, integer btnId, real time returns nothing
        call SaveReal(skillBtnHash, btnId, uid * 100 + 5, time)
    endfunction
    // 获取按钮的施法结束CD计时
    function getSkillButtonEndingCDTime takes integer uid, integer btnId returns real
        return LoadReal(skillBtnHash, btnId, uid * 100 + 5)
    endfunction

    // 设置按钮的显示图标
    function setSkillButtonIcon takes integer uid, integer btnId, string iconPath returns nothing
        call SaveStr(skillBtnHash, btnId, uid * 100 + 7, iconPath)
    endfunction
    // 获取按钮的显示图标
    function getSkillButtonIcon takes integer uid, integer btnId returns string
        return LoadStr(skillBtnHash, btnId, uid * 100 + 7)
    endfunction

    // 获取指定技能的按钮id
    function getSkillButtonId takes integer uid, integer skillId returns integer
        local integer btnId = 1
        loop
            exitwhen btnId > 8
            if getSkillButtonSkillId(uid, btnId) == skillId then
                return btnId
            endif
            set btnId = btnId + 1
        endloop

        return 0
    endfunction

    // 添加技能按钮 return 按钮id  返回0表示创建失败，格子已经满了
    function newSkillButton takes integer uid, integer skillId, string iconPath, real startingCD, real endCd returns integer
        local integer btnId

        if getSkillButtonNum(uid) > 8 then
            return 0
        endif

        // 技能学习的技能Id
        set unlockedSkillId[uid * 20 + unlockedSkillIdCount[uid]] = 1
        set unlockedSkillIdCount[uid] = unlockedSkillIdCount[uid] + 1

        // 添加数量
        call setSkillButtonNum(uid, getSkillButtonNum(uid) + 1)
        set btnId = getSkillButtonNum(uid)
        // 启动按钮
        call startSkillButton(uid, btnId)

        call setSkillButtonSkillId(uid, btnId, skillId)
        call setSkillButtonIcon(uid, btnId, iconPath)
        call setSkillButtonStartingCD(uid, btnId, startingCD)
        call setSkillButtonStartingCDTime(uid, btnId, startingCD)
        call setSkillButtonEndingCD(uid, btnId, endCd)
        call setSkillButtonEndingCDTime(uid, btnId, endCd)

        // 显示技能按钮
        call setSkillButtonIconShow(uid, btnId, iconPath)

        return btnId
    endfunction

    // 释放技能
    // 施法指定ID的技能
    // TODO
    function releaseSkillByID takes integer uid, integer skillId returns nothing
        
        local real x = GetUnitX(udg_player_select_hero[uid])
        local real y = GetUnitY(udg_player_select_hero[uid])

        call SetUnitAnimation( udg_player_select_hero[uid], "Attack" )
        // 飞剑术
        if skillId == 1 then
            call BJDebugMsg("释放 - 飞剑术")
            call releaseFanAttack(uid, x, y)
        // 火焰弹
        elseif skillId == 2 then
            call BJDebugMsg("释放 - 火焰弹")
            call releseHYD(uid)
        // 掌心雷
        elseif skillId == 3 then
            call BJDebugMsg("释放 - 掌心雷")
            call releseZXL(uid)
        // 闪电链
        elseif skillId == 4 then
            call BJDebugMsg("释放 - 闪电链")
            call releseSDL(uid)
        // 寒冰箭
        elseif skillId == 5 then
            call BJDebugMsg("释放 - 寒冰箭")
            call releaseHbj(uid, x, y)
        endif

    endfunction

    // 执行指定玩家的技能按钮
    function executeSkillButton takes integer uid returns nothing
        // 总共有8个技能格子，全部判断
        local real timerI = 0.1
        local real prossI = 0.0
        local integer btnId = 1
        loop
            exitwhen btnId > 8
            
            // 判断按钮是否启动
            if isSkillButtonStart(uid, btnId) then
                // 表示拥有释放持续CD
                if getSkillButtonStartingCDTime(uid, btnId) < getSkillButtonStartingCD(uid, btnId) then

                    call setSkillButtonStartingCDTime(uid, btnId, getSkillButtonStartingCDTime(uid, btnId) + timerI)
                    // ====== 模型进度显示 ======
                    // CD总时间 / 计时器时间 = 计时器要执行的次数
                    // 执行的次数 * 每次累加 = 1
                    set prossI = 1.0 / (getSkillButtonStartingCD(uid, btnId) / timerI)
                    call setSkillButtonStartingCDProgress(uid, btnId, getSkillButtonStartingCDProgress(uid, btnId) + prossI)
                    if Player(uid) == GetLocalPlayer() then
                        call DzFrameSetAnimateOffset( getSkillButtonModel(btnId), getSkillButtonStartingCDProgress(uid, btnId) )
                    endif
                    // ====== 模型进度显示 ======

                else
                    if Player(uid) == GetLocalPlayer() then
                        call DzFrameSetAnimateOffset( getSkillButtonModel(btnId), 1.0 )
                    endif
                    // 执行结束CD
                    if getSkillButtonEndingCDTime(uid, btnId) < getSkillButtonEndingCD(uid, btnId) then
                        call setSkillButtonEndingCDTime(uid, btnId, getSkillButtonEndingCDTime(uid, btnId) + timerI)
                        // ====== 模型进度显示 ======
                        // CD总时间 / 计时器时间 = 计时器要执行的次数
                        // 执行的次数 * 每次累加 = 1
                        set prossI = 1.0 / (getSkillButtonEndingCD(uid, btnId) / timerI)
                        call setSkillButtonEndingCDProgress(uid, btnId, getSkillButtonEndingCDProgress(uid, btnId) + prossI)
                        if Player(uid) == GetLocalPlayer() then
                            // call DisplayTextToPlayer(Player(uid), 0, 0, "pross = " + R2S(getSkillButtonEndingCDProgress(uid, btnId)) + "btnId: " + I2S(btnId))
                            call DzFrameSetAnimateOffset( getSkillButtonModelEnd(btnId), getSkillButtonEndingCDProgress(uid, btnId) )
                        endif
                        // ====== 模型进度显示 ======
                    else
                        // 清空CD
                        call setSkillButtonStartingCDTime(uid, btnId, 0.0)
                        call setSkillButtonStartingCDProgress(uid, btnId, 0.0)
                        call setSkillButtonEndingCDTime(uid, btnId, 0.0)
                        call setSkillButtonEndingCDProgress(uid, btnId, 0.0)
                        if Player(uid) == GetLocalPlayer() then
                            call DzFrameSetAnimateOffset( getSkillButtonModelEnd(btnId), 1.0 )
                        endif

                        // CD结束，调用技能
                        call releaseSkillByID(uid, getSkillButtonSkillId(uid, btnId))
                    endif
                endif

            endif
            set btnId = btnId + 1
        endloop
    endfunction

    // CD计时器
    function skillButtonCDTimer takes nothing returns nothing
        local integer uid = 0
        loop
            exitwhen uid > PLAYER_NUMBER
            if isPlayerOnline(uid) then
                call executeSkillButton(uid)
            endif
            set uid = uid + 1
        endloop
    endfunction

    private function init takes nothing returns nothing
        local timer t = CreateTimer()

        call TimerStart(t, 0.10, true, function skillButtonCDTimer)

        set t = null
    endfunction
endlibrary


